/*
 * WFQueue.h
 * A wait free queue
 * @author Hani shubin
 */
#ifndef WFQUEUE_
#define WFQUEUE_

#include "Node.h"

/*
 * USE_HP is a compilation flag that indicates whether the queue uses the HP
 * method or not.
 */
#ifdef USE_HP
#include "MemoryManager.h"
#endif

/**
 * A state of a thread:
 * 	phase: it's phase
 *  pending: if it's pending
 *  enquueOp: true of it's current operation is enqueue
 *  node: the node that is enqueued/dequeued
 */
typedef struct OpDesc_t {
	long phase;
	void* data;
} OpDesc;

/**
 * Queue data.
 * 		head- the head of the queue
 * 		tail- the tail of the queue
 * 		states- an array of OpDesc for each thread
 * 		numOfThreads- number of threads that uses the queue
 * 		memoryManager- the MemoryManager of the queue
 */
typedef struct WFQueue_t{
	Node* head;
	Node* tail;
	OpDesc* states;
	unsigned int numOfThreads;
	#ifdef USE_HP
	MemoryManager* memoryManager;
	#endif
}WFQueue;

/**
 * Get a WFQueue (c'tor).
 * Input: numOfThreads that will use the WFQueue.
 * Output: a new initialized WFQueue.
 */
inline WFQueue* getQueue(unsigned int numOfThreads);

/**
 * Delete a WFQueue (d'tor).
 * Input: a WFQueue to be deleted.
 * Assumption: 	This function must be called after all threads have finished
 * 				running.
 */
inline void deleteQueue(WFQueue* queue);

/**
 * Insert a value to the queue.
 * Input: 	queue- the queue where the value should be inserted
 * 			myTid- the tid of the inserting thread
 * 			value- the value to be inserted
 */
inline void enq(WFQueue* queue, long long myTid, int value);

/**
 * Remove a value from the queue.
 * Input: 	queue- the queue from where to take a value
 * 			myTid- the tid of the removing thread
 * Output: 	the value that was taken from the queue
 * 			or -1 if the queue is empty
 */
int deq(WFQueue* queue, long long myTid);

/**
 * Print queue nodes
 */
inline void printQueue(WFQueue* queue);
/**
 * Print queue size
 */
inline void printQueueSize(WFQueue* queue);


#endif /* WFQUEUE_ */
